/**
 * 滑块验证码生成工具
 * 基于UniApp canvas API实现，兼容FirstUI滑块验证组件
 */

/**
 * 生成滑块验证码
 * @param {String} imageUrl - 图片URL
 * @param {Object} options - 配置选项
 * @returns {Promise<Object>} - 返回背景图、拼图和位置信息
 */
export function createSliderCaptcha(imageUrl, options = {}) {
  console.log('开始生成滑块验证码', imageUrl);
  
  // 默认配置
  const config = {
    width: 320,                // 图片宽度
    height: 160,               // 图片高度
    sliderWidth: 44,           // 滑块宽度（FirstUI默认为44px）
    sliderHeight: 44,          // 滑块高度（FirstUI默认为44px）
    sliderRadius: 8,           // 滑块圆角半径
    interfereLines: 8,         // 干扰线数量
    interfereDots: 100,        // 干扰点数量
    bgCanvasId: 'bgCanvas',    // 背景画布ID
    sliderCanvasId: 'sliderCanvas', // 滑块画布ID
    cutCanvasId: 'cutCanvas',  // 裁剪画布ID
    ...options
  };
  
  return new Promise((resolve, reject) => {
    try {
      // 固定y坐标为画布高度的中间位置减去滑块高度的一半
      // 这样可以确保每次生成的滑块都在同一高度
      const y = Math.floor((config.height - config.sliderHeight) / 2);
      
      // x坐标随机生成，但避开边缘
      const x = Math.floor(Math.random() * (config.width - config.sliderWidth - 80)) + 40;
      
      console.log('滑块位置:', x, y);
      
      // 确保画布已准备好
      setTimeout(() => {
        // 获取图片信息
        uni.getImageInfo({
          src: imageUrl,
          success: (imgInfo) => {
            // 创建背景画布上下文
            const bgCtx = uni.createCanvasContext(config.bgCanvasId);
            
            // 清除画布
            bgCtx.clearRect(0, 0, config.width, config.height);
            
            // 绘制背景图
            bgCtx.drawImage(imgInfo.path, 0, 0, config.width, config.height);
            
            // 创建裁剪画布上下文（用于裁剪出滑块部分）
            const cutCtx = uni.createCanvasContext(config.cutCanvasId);
            
            // 清除画布
            cutCtx.clearRect(0, 0, config.width, config.height);
            
            // 先在裁剪画布上绘制完整图片
            cutCtx.drawImage(imgInfo.path, 0, 0, config.width, config.height);
            
            // 在背景上绘制滑块形状（与FirstUI兼容的形状）
            drawSliderShape(bgCtx, x, y, config);
            
            // 在背景图上添加干扰
            addInterference(bgCtx, config);
            
            // 在裁剪画布上裁剪出滑块
            cutSliderImage(cutCtx, x, y, config);
            
            // 绘制完成后导出图片
            bgCtx.draw(true, () => {
              setTimeout(() => {
                uni.canvasToTempFilePath({
                  canvasId: config.bgCanvasId,
                  success: (bgRes) => {
                    // 绘制滑块
                    cutCtx.draw(true, () => {
                      setTimeout(() => {
                        uni.canvasToTempFilePath({
                          canvasId: config.cutCanvasId,
                          x: x,
                          y: y,
                          width: config.sliderWidth,
                          height: config.sliderHeight,
                          success: (sliderRes) => {
                            console.log('滑块验证码生成成功');
                            
                            // 注意：这里返回的x是滑块的正确位置，而不是滑动距离
                            // FirstUI组件需要的是滑块相对于左边界的位置
                            resolve({
                              bgImage: bgRes.tempFilePath,
                              sliderImage: sliderRes.tempFilePath,
                              position: { x, y },
                              // 添加滑动距离，用于验证
                              sliderDistance: x
                            });
                          },
                          fail: (err) => {
                            console.error('导出滑块图片失败:', err);
                            reject(err);
                          }
                        });
                      }, 300);
                    });
                  },
                  fail: (err) => {
                    console.error('导出背景图片失败:', err);
                    reject(err);
                  }
                });
              }, 300);
            });
          },
          fail: (err) => {
            console.error('加载图片失败:', err);
            reject(err);
          }
        });
      }, 100);
    } catch (error) {
      console.error('生成滑块验证码失败:', error);
      reject(error);
    }
  });
}

/**
 * 在背景上绘制滑块形状
 * @param {CanvasContext} ctx - 画布上下文
 * @param {Number} x - 滑块x坐标
 * @param {Number} y - 滑块y坐标
 * @param {Object} config - 配置
 */
function drawSliderShape(ctx, x, y, config) {
  const { sliderWidth, sliderHeight } = config;
  
  // 绘制FirstUI风格的滑块形状（拼图形状）
  ctx.beginPath();
  
  // 绘制基本矩形
  ctx.rect(x, y, sliderWidth, sliderHeight);
  
  // 在背景上绘制黑色遮罩
  ctx.setFillStyle('rgba(0, 0, 0, 0.5)');
  ctx.fill();
  
  // 绘制滑块边框
  ctx.setStrokeStyle('#ffffff');
  ctx.setLineWidth(1);
  ctx.stroke();
}

/**
 * 在裁剪画布上裁剪出滑块
 * @param {CanvasContext} ctx - 画布上下文
 * @param {Number} x - 滑块x坐标
 * @param {Number} y - 滑块y坐标
 * @param {Object} config - 配置
 */
function cutSliderImage(ctx, x, y, config) {
  const { sliderWidth, sliderHeight } = config;
  
  // 保存当前状态
  ctx.save();
  
  // 创建裁剪路径
  ctx.beginPath();
  ctx.rect(x, y, sliderWidth, sliderHeight);
  
  // 设置裁剪区域
  ctx.clip();
  
  // 绘制边框
  ctx.setStrokeStyle('#ffffff');
  ctx.setLineWidth(2);
  ctx.stroke();
  
  // 恢复状态
  ctx.restore();
}

/**
 * 添加干扰元素
 * @param {CanvasContext} ctx - 画布上下文
 * @param {Object} config - 配置
 */
function addInterference(ctx, config) {
  const { width, height, interfereLines, interfereDots } = config;
  
  // 添加干扰线
  for (let i = 0; i < interfereLines; i++) {
    ctx.beginPath();
    ctx.setStrokeStyle(`rgba(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255}, 0.3)`);
    ctx.moveTo(Math.random() * width, Math.random() * height);
    ctx.lineTo(Math.random() * width, Math.random() * height);
    ctx.stroke();
  }
  
  // 添加干扰点
  for (let i = 0; i < interfereDots; i++) {
    ctx.beginPath();
    ctx.setFillStyle(`rgba(${Math.random() * 255}, ${Math.random() * 255}, ${Math.random() * 255}, 0.3)`);
    ctx.arc(Math.random() * width, Math.random() * height, Math.random() * 2, 0, Math.PI * 2);
    ctx.fill();
  }
}

/**
 * 验证滑块位置是否正确
 * @param {Number} sliderX - 用户滑动的X坐标
 * @param {Number} correctX - 正确的X坐标
 * @param {Number} tolerance - 容错范围
 * @returns {Boolean} - 是否验证通过
 */
export function verifySliderPosition(sliderX, correctX, tolerance = 5) {
  return Math.abs(sliderX - correctX) <= tolerance;
} 